#include "Common.h"

#include <windows.h>
#include <cstdio>

void CommonOperator::OutputTxt(const char *text, const bool line) {
    if (text && *text)
    {
        printf("%s%s", text, line ? "\n" : "");
    }
    else
    {
        printf(line ? "\n" : "");
    }
}

void CommonOperator::OutputBool(const int value, const char *pre_txt, const char *post_txt, const bool line) {
    printf("%s%s%s%s", pre_txt ? pre_txt : "", value ? "true" : "false", post_txt ? post_txt : "", line ? "\n" : "");
}

void CommonOperator::OutputDec(const int64 value, const char *pre_text, const char *post_text, const bool line) {
    printf("%s%I64d%s%s", pre_text ? pre_text : "", value, post_text ? post_text : "", line ? "\n" : "");
}

void CommonOperator::OutputFloat(const double value, const char *pre_text, const char *post_text, const bool line) {
    printf("%s%5.2lf%s%s", pre_text ? pre_text : "", value, post_text ? post_text : "", line ? "\n" : "");
}

void CommonOperator::OutputHex02(const byte value, const char *pre_txt, const char *post_txt, const bool line) {
    printf("%s%02X%s%s", pre_txt ? pre_txt : "", value, post_txt ? post_txt : "", line ? "\n" : "");
}

void CommonOperator::OutputHex04(const ushort value, const char *pre_txt, const char *post_txt, const bool line) {
    printf("%s%04X%s%s", pre_txt ? pre_txt : "", value, post_txt ? post_txt : "", line ? "\n" : "");
}

void CommonOperator::OutputHex08(const uint value, const char *pre_txt, const char *post_txt, const bool line) {
    printf("%s%08X%s%s", pre_txt ? pre_txt : "", value, post_txt ? post_txt : "", line ? "\n" : "");
}

void CommonOperator::OutputHex16(const uint64 value, const char *pre_txt, const char *post_txt, const bool line) {
    printf("%s%016I64X%s%s", pre_txt ? pre_txt : "", value, post_txt ? post_txt : "", line ? "\n" : "");
}

void CommonOperator::OutputIpv4(const uint ip, const char *pre_txt, const char *post_txt, const bool line) {
    printf("%s%d.%d.%d.%d%s%s", pre_txt ? pre_txt : "", ip >> 24 & 0xFF, ip >> 16 & 0xFF, ip >> 8 & 0xFF, ip >> 0 & 0xFF, post_txt ? post_txt : "",
        line ? "\n" : "");
}

void CommonOperator::OutputErr(const KSError error, const char *func_name, const char *comment) {
    if (error == KS_OK) {return;}

    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
    GetConsoleScreenBufferInfo(hConsole, &consoleInfo);

    SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_INTENSITY);
    const char *pError;
    KS_getErrorString(error, &pError, KSLNG_DEFAULT);
    printf("ERROR (0x%08X = \'%s\') -\n  %s: %s\n", error, pError, func_name, comment);

    SetConsoleTextAttribute(hConsole, consoleInfo.wAttributes);
    if (KS_getErrorDescription(error, func_name, &pError, KSLNG_DEFAULT) == KS_OK)
    {
        OutputTxt(pError);
    }
}


int CommonOperator::inputDec(const char* pPreText, int defaultVal) {
  char pBuf[32];
  sprintf_s(pBuf, "%d", defaultVal);
  return inputDec(pPreText, pBuf);
}

int CommonOperator::inputDec(const char* pPreText, const char* pDefault) {
  int dec = 0;
  sscanf_s(inputTxt(pPreText, pDefault), "%d", &dec);
  return dec;
}

#define KSMP_INPUTBUFFERSIZE 256
//------ inputTxt ------
char* CommonOperator::inputTxt(const char* pPreText, const char* pDefault) {
  printf("%s", pPreText);
  if (pDefault && *pDefault)
    printf("[%s] ", pDefault);
  static char _pBuffer[KSMP_INPUTBUFFERSIZE];
  for (int i = 0;;) {
    int ch = myGetch();
    if (isprint(ch))
      myPutch(ch);
    if (ch == '\b') {
      if (i > 0) {
        --i;
        printf("\b \b");
      }
      continue;
    }
    if (ch == '\r' || i == KSMP_INPUTBUFFERSIZE - 1) {
      printf("\n");
      if (i == 0)
        strcpy(_pBuffer, pDefault);
      else
        _pBuffer[i] = '\0';
      break;
    }
    if (isprint(ch))
      _pBuffer[i++] = ch;
  }
  return _pBuffer;
}
#undef KSMP_INPUTBUFFERSIZE

std::string CommonOperator::GetErrorStr(const KSError error) {
    const char* errorStr;
    KS_getErrorString(error, &errorStr, KSLNG_DEFAULT);
    return std::string(errorStr);
}

void CommonOperator::waitTime(uint time) {
  int delay = time / 10000;
  Sleep(delay);
}
